﻿using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.GamePlay;
using LFloatMath.Math;

namespace IQIGame.Onigao.Logic
{
    public class SkillPart : IReusableClass
    {
        public long guid;
        public string name;
        public string timeline;
        public ESkillPartType partType;
        public int aiMoveType;
        
        public Skill skill { get; set; }
        public List<SkillEffectiveData> effectives;
        public SkillCondition condition;
        public SkillPart next;

        public TargetSelect tempSelect;

        public bool enabled = false;

        public void OnEnable()
        {
            this.enabled = true;
            for (int i = 0; i < this.effectives.Count; i++)
            {
                var rData = this.effectives[i];
                rData.effective.OnEnable(rData, this.skill.executer);
            }
        }

        public void OnDisable()
        {
            this.enabled = false;

            this.ResetTempData();
            for (int i = 0; i < this.effectives.Count; i++)
            {
                var rData = this.effectives[i];
                rData.effective.OnDisable(rData, this.skill.executer);
            }
        }

        public void Execute(ref SkillResponse rSkillResp, SelectParam rSelectParam, object param)
        {
            var rResultCtrl = this.skill.executer.battle.playCtrl.resultCtrl;

            // Part执行占位
            var rPartPOD = BattleUpdateFactory.Create();
            rResultCtrl.Add(rPartPOD);
            var rPartCommand = BaseBattleCommand.Get<BattleCommand_StartPart>();
            rPartCommand.partGUID = this.guid;
            rPartCommand.skillID = this.skill.skillID;
            rPartCommand.targetGUID = new List<int>[this.effectives.Count];
            rPartCommand.aiMoveType = this.aiMoveType;
            
            var rContext = rSkillResp.CreateContext();
            rContext.skill = this.skill;
            rContext.part = this;
            rContext.param = param; // 外部传递的参数
            rContext.selectParam = rSelectParam;
            var rCorrect = rContext.correct;
            for (int i = 0; i < this.effectives.Count; i++)
            {
                rContext.correct.attacker = this.skill.executer;
                var rEffective = this.effectives[i];
                TargetSelect rTargetSelect;
                if (this.tempSelect != null)
                {
                    rTargetSelect = this.tempSelect;
                    rTargetSelect.guid = rEffective.select.guid;
                }
                else
                {
                    rTargetSelect = rEffective.select;
                }

                this.skill.executer.battle.playCtrl.triggerCtrl.Broadcast(EBattleTriggerType.Battle_SkillEffectTempModify, rContext);
                var rTargetsGUID = new List<int>();
                this.effectives[i].effective.Execute(rEffective, rTargetSelect, rSelectParam, ref rContext, ref rTargetsGUID, i);
                rPartCommand.targetGUID[i] = rTargetsGUID;
            }

            BattleUpdateFactory.SetSkillPartData(this.skill.executer.GUID, rPartCommand, rPartPOD);

            // 这里进行集中的死亡检查
            var rAllUnits = this.skill.executer.battle.playCtrl.unitCtrl.units;
            for (int i = 0; i < rAllUnits.Count; i++)
            {
                var rUnit = rAllUnits[i];
                if (rUnit.IsDead(true, false))
                {
                    rUnit.GetComponent<DeadComponent>(ETComponentType.DeadComponent).Dead();
                }
            }

            // 执行可能导致自己被关闭或移除，若移除则不再执行后续
            if (!this.enabled)
            {
                return;
            }
            if (this.next != null)
            {
                rSkillResp.nextPart = this.next;
            }
            else if (this.condition != null)
            {
                rSkillResp.nextPart = this.condition.GetExecute(rSkillResp);
            }
            else
            {
                rSkillResp.nextPart = null;
            }
            this.ResetTempData();
        }

        private void ResetTempData()
        {
            this.skill.tempType = ESkillType.None;
            this.tempSelect = null;
        }

        private SkillResponse m_PartResp;
        public uint MaxStore => 10;

        public void OnReset()
        {
            this.effectives = null;
            this.next = null;
            this.skill = null;
            this.name = default;
            this.guid = default;
            this.timeline = default;
        }

#if UNITY_EDITOR
        public override string ToString()
        {
            var s = "";
            for (int i = 0; i < this.effectives.Count; i++)
            {
                s += $"[{this.effectives[i].ToString()}]\n";
            }
            return s;
        }
#endif
    }


    public class SkillCorrect
    {
        public SkillCorrect(SkillEffectiveContext context)
        {
            this.context = context;
        }

        public SkillEffectiveContext context { get; private set; }


        public TargetSelect select;
        public Unit attacker;
        public Unit defender;

        public LFloat tempDamageModify;
        public LFloat tempHurtModify;

        /// <summary>
        /// 除了context全部重置
        /// </summary>
        public void Reset()
        {
            this.attacker = null;
            this.defender = null;
            this.select = null;

            this.tempDamageModify = LFloat.zero;
            this.tempHurtModify = LFloat.zero;
        }

        /// <summary>
        /// 重置不跨效果的内容
        /// </summary>
        public void ResetTempValue()
        {
            this.tempDamageModify = LFloat.zero;
            this.tempHurtModify = LFloat.zero;
        }
    }

    public enum ESkillCorrectParmaType
    {
    }
}